import bluetooth
import struct
from ble_advertising import advertising_payload

_IRQ_CENTRAL_CONNECT = 1
_IRQ_CENTRAL_DISCONNECT = 2
_IRQ_GATTS_WRITE = 3
_IRQ_GATTC_NOTIFY = 4

# 自定义服务和特征的 UUID
_SERVICE_UUID = bluetooth.UUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b")
_CHAR_UUID = bluetooth.UUID("beb5483e-36e1-4688-b7f5-ea07361b26a8")


class BLEReceiver:
    def __init__(self, ble,  name="bluetoth"):
        self._ble = ble
        self._ble.active(True)
        self._ble.irq(self._irq)
        self._conn_handle = None
        self._char_handle = None
        self._received_data = bytearray()
        self._total_length = 0
        self._received_chunks = {}
        
        self._payload = advertising_payload(name=name, services=[_SERVICE_UUID])
        self._advertise()

    def _irq(self, event, data):
        if event == _IRQ_CENTRAL_CONNECT:
            conn_handle, _, _ = data
            self._conn_handle = conn_handle
            self._discover_services()
        elif event == _IRQ_CENTRAL_DISCONNECT:
            self._conn_handle = None
            self._char_handle = None
            self._received_data = bytearray()
            self._total_length = 0
            self._received_chunks = {}
        elif event == _IRQ_GATTC_NOTIFY:
            conn_handle, value_handle, notify_data = data
            if conn_handle == self._conn_handle and value_handle == self._char_handle:
                total_length, chunk_index = struct.unpack('>HH', notify_data[:4])
                chunk = notify_data[4:]
                if total_length != self._total_length:
                    self._total_length = total_length
                    self._received_chunks = {}
                self._received_chunks[chunk_index] = chunk
                if len(self._received_chunks) * 16 >= self._total_length:
                    self._assemble_data()

    def _advertise(self, interval_us=500000):
        self._ble.gap_advertise(interval_us, adv_data=self._payload)
        
    def _discover_services(self):
        services = self._ble.gattc_discover_services(self._conn_handle)
        for service in services:
            if service.uuid == _SERVICE_UUID:
                characteristics = self._ble.gattc_discover_characteristics(
                    self._conn_handle, service.handle
                )
                for char in characteristics:
                    if char.uuid == _CHAR_UUID:
                        self._char_handle = char.handle
                        self._ble.gattc_notify(self._conn_handle, self._char_handle, True)

    def _assemble_data(self):
        for i in range(len(self._received_chunks)):
            self._received_data.extend(self._received_chunks[i])
        print("Received all data:", bytes(self._received_data))


# 初始化 BLE
ble = bluetooth.BLE()
receiver = BLEReceiver(ble)